/**
 *  29/lug/07 - 16:24:53
 *  Create by hachreak
 *  Under GPL V2 license
 */

package it.secondlifelab.p2pSL.jserver;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.Ostermiller.util.MD5;

/**
 * @author hachreak
 * 
 * Class for load the directory shared
 */
public class DirectoryLoader {

	public static String fileConfig = "config/directory.ini";

	private List<String> directory = new ArrayList<String>();
	
	/**
	 * Md5 di tutti i file condivisi
	 */
	//private List<String> md5Files = new ArrayList<String>();

	private List<File> dirs = new ArrayList<File>();

	private Map<String,File> files = new HashMap<String,File>();

	/**
	 * Load directory shared
	 * 
	 * @throws IOException
	 */
	public DirectoryLoader() throws IOException {
		File f = new File(fileConfig);
		
		if(!f.exists())
			f.createNewFile();
		
		BufferedReader br = new BufferedReader(new InputStreamReader(
				new FileInputStream(f)));
		String line;
		// Carica tutte le directory condivise
		while ((line = br.readLine()) != null) {
			// br.readLine();
			directory.add(line);
			// System.out.println(line);
		}
	}

//	/**
//	 * Get list of all directories shared
//	 * 
//	 * @return list of directories shared
//	 */
//	public List<File> getDirectories() {
//		if (dirs.size() == 0) {
//
//			Iterator<String> i = this.directory.iterator();
//			while (i.hasNext()) {
//				String file = i.next();
//				if (new File(file).isDirectory()) {
//					this.getDirectoriesList(i.next());
//				} else {
//					files.add(new File(file));
//				}
//			}
//		}
//		return dirs;
//	}

//	private void getDirectoriesList(String directory) {
//
//		File allDir = new File(directory);
//
//		// It is also possible to filter the list of returned files.
//		// This example does not return any files that start with `.'.
//		File[] files = allDir.listFiles(new FileFilter() {
//			public boolean accept(File file) {
//				return file.isDirectory();
//			}
//		});
//
//		for (int i = 0; i < files.length; i++) {
//			//System.out.println(files[i].getPath());
//			dirs.add(files[i]);
//			this.getDirectoriesList(files[i].getPath());
//		}
//		// return dirs;
//	}

	/**
	 * Get list of all files shared
	 * 
	 * @return list of files shared
	 * @throws IOException 
	 */
	public Map<String,File> getFiles() throws IOException {
		if (files.size() == 0) {

			Iterator<String> i = this.directory.iterator();
			while (i.hasNext())
				this.getFilesList(i.next());
		}
		return files;
	}

	private void getFilesList(String directory) throws IOException {
		File allDir = new File(directory);

		if (allDir.isDirectory()) {
			// Crea un filtro per recuperare i file nella directory non nascosti
			File[] fileList = allDir.listFiles(new FileFilter() {
				public boolean accept(File file) {
					return file.isFile() && !file.isHidden();
				}
			});

			// Aggiungi i file alla lista
			for (int i = 0; i < fileList.length; i++) {
				files.put(MD5.getHashString(fileList[i]), fileList[i]);
			}

			// Filtro: ricava solo le directory
			File[] dir = allDir.listFiles(new FileFilter() {
				public boolean accept(File file) {
					return file.isDirectory();
				}
			});

			// per ogni directory richiama questa funzione
			for (int i = 0; i < dir.length; i++) {
				dirs.add(dir[i]);
				this.getFilesList(dir[i].getPath());
			}

		} else {
			files.put(MD5.getHashString(allDir), allDir);
		}
	}

	public boolean containFile(File file) throws IOException {
		
		//if (!file.getPath().startsWith("/"))
		//	file = new File("./" + file.getPath());
		
		return getFiles().containsValue(file);
	}

//	public boolean containDir(File file) {
//		if (dirs.size() == 0)
//			this.getDirectories();
//		if (!file.getPath().startsWith("/"))
//			file = new File("./" + file.getPath());
//		return this.dirs.contains(file);
//	}

	public boolean containMD5(String md5) throws IOException{
		return getFiles().containsKey(md5);
	}
	
	public List<String> getDirectoriesShared() throws IOException {
		getFiles();
		return this.directory;
	}
//	
//	public List<String> getMd5Files() throws IOException{
//		getFiles();
//		return md5Files;
//	}

	public File getFile(String md5) {
		return files.get(md5);
	}
	
	/**
	 * Search for a patter
	 * @param pattern stringa da cercare
	 * @param comp comparatore
	 * @return
	 * @throws IOException
	 */
	public Map<String,File> search(String pattern, Comparator<String> comp) throws IOException{
		Map<String,File> m = this.getFiles();
		Iterator<String> i = m.keySet().iterator();
		
		Map<String,File> out = new HashMap<String,File>();
		
		while(i.hasNext()){
			String md5 = i.next();
			File file = m.get(md5);
			
			if(comp.compare(file.getPath(), pattern) == 0){
				out.put(md5, file);
			}
		}
		return out;
	}
}
